# -*- coding: utf-8 -*-
import copy
import datetime
import hashlib
import json
import os
import random
import time
from collections import OrderedDict

import pytz
from bs4 import element

from plugin.utils.id_utils import get_hash_id_enhance


def get_extension_from_file_url(url):
    if not url:
        return None
    try:
        file_name = os.path.basename(url)
        file_extension = file_name.split('.')
        if len(file_extension) >= 2:
            return file_extension[-1]
        else:
            return None
    except Exception as e:
        return None


def parse_timestamp(timestamp):
    timestamp = int(timestamp)
    if timestamp > 9999999999:
        timestamp /= 1000
    return utils_mongo_time(datetime.datetime.fromtimestamp(timestamp))


tz_cn = pytz.timezone('Asia/Shanghai')


def utils_mongo_time(dtime, timezone=tz_cn):
    return timezone.localize(dtime)


def get_today_str():
    return datetime.datetime.now().strftime('%Y-%m-%d')


def get_now_str():
    return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')


def get_time():
    return int(time.time())


def get_delta_day(delta_day):
    return datetime.datetime.strftime(datetime.datetime.now() + datetime.timedelta(delta_day), '%Y-%m-%d')


def format_time(time_str, format_str, *args):
    try:
        _date = datetime.datetime.strptime(time_str, format_str)
        return _date
    except Exception as e:
        errors = [e]
        for format_arg in args:
            if format_arg is None:
                continue
            try:
                _date = datetime.datetime.strptime(time_str, format_arg)
                return _date
            except Exception as e1:
                errors.append(e1)
        print(errors)
        return ''


def clean_string(input_str):
    return input_str.strip() if input_str else ''


HTML_PREFIX = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>%s</title>
</head>
<body><br><br><br>
"""


def clean_html(bs_node, title):
    """

    :param bs_node: main body
    :param title: html title
    :return: document
    """
    if bs_node is None:
        return None
    html_head = HTML_PREFIX % title
    # if isinstance(bs_node, element.Tag):
    #     # 移除外链
    #     link_nodes = bs_node.find_all("a")
    #     for link in link_nodes:
    #         link.decompose()
    #     result = bs_node.prettify().replace(u'附件：', '').replace(u'附件:', '').replace('<br/>', '<br/><br/>')
    # else:
    html_body = str(bs_node)
    return '\n'.join([html_head, html_body, '</body></html>'])


def clean_html_simple(bs_node, title):
    if bs_node is None:
        return None
    result = ''
    html_head = HTML_PREFIX % title
    if isinstance(bs_node, element.Tag):
        # 移除外链
        link_nodes = bs_node.find_all("a")
        for link in link_nodes:
            link.decompose()
        # s = str(bs_node)
        result = bs_node.text.replace('附件：', '').replace('附件:', '').replace('\n', '<br>')
    else:
        result = str(bs_node)
    return '\n'.join([html_head, result, '</body></html>'])


def convert_to_raw_result(result):
    if not result:
        return result
    elif isinstance(result, dict):
        if isinstance(result, OrderedDict):
            result['__sort'] = json.dumps(list(result.keys()))
        return {k: convert_to_raw_result(v) for k, v in result.items()}
    elif isinstance(result, list):
        return [convert_to_raw_result(i) for i in result]
    elif isinstance(result, datetime.datetime):
        return '__datetime_obj__%s' % result.strftime('%Y-%m-%d %H:%M:%S.%f')
    else:
        return result


def dumps_resault(result):
    return json.dumps(convert_to_raw_result(result))


def convert_from_raw_result(result):
    if not result:
        return result
    elif isinstance(result, dict):
        tmp = tuple(((k, convert_from_raw_result(result[k])) for k in json.loads(result.get('__sort', '[]'))))
        return {k: convert_from_raw_result(v) for k, v in result.items()} if not tmp else OrderedDict(tmp)
    elif isinstance(result, list):
        return [convert_from_raw_result(i) for i in result]
    elif isinstance(result, str):
        if result.startswith('__datetime_obj__'):
            return datetime.datetime.strptime(result[len('__datetime_obj__'):], '%Y-%m-%d %H:%M:%S.%f')
        else:
            return result
    else:
        return result


def load_resault(resault):
    return convert_from_raw_result(json.loads(resault))


def md5_generator(url, data={}, end_time='', **kwargs):
    """
    生成md5
    :param url:
    :param data:
    :param end_time:
    :return:
    """
    target = ''
    try:
        target = str(url) + str(data) + str(end_time)
    except UnicodeEncodeError:
        target = _encode(url, data, end_time)
    except UnicodeDecodeError:
        target = _encode(url, data, end_time)
    if kwargs is not None:
        target += str(kwargs)
    return hashlib.md5(target).hexdigest()


def _encode(url, data, end_time):
    unicode_type = type('')
    if type(url) == unicode_type:
        url = url.encode('utf-8')
    if type(data) == unicode_type:
        data = data.encode('utf-8')
    if type(data) == unicode_type:
        end_time = end_time.encode('utf-8')
    # print(type(url), type(data), type(end_time))
    return url + data + end_time


def get_random_number(from_num, to_num=100):
    return random.randint(from_num, to_num)


def get_zfill_random_number(n):
    width = n
    if width < 1:
        width = 1
    s = "1"
    for i in range(1, width):
        s += "0"
    to_num = int(s)
    r = get_random_number(0, to_num)
    return str(r).zfill(width)


def get_report():
    # 定义https://confluence.abcft.com/pages/viewpage.action?pageId=3775514
    item = {}
    item['source_url'] = ''
    item['file_url'] = ''  # 文件获取url
    item['file_size'] = 0
    item['file_type'] = ''  # 文件类型
    item['oss_path'] = ''
    item['pdf_pages'] = 0
    item['industryname'] = ''
    item['stock_code'] = ''
    item['stock_name'] = ''
    item['rating'] = ''
    item['tags'] = ''

    # deprecated
    item['sitename'] = ''
    item['markettype'] = '1'
    item['category_id'] = ''
    item['industry_id'] = ''
    item['source'] = ''

    item['author'] = ''
    item['title'] = ''
    item['publish'] = ''
    item['summary'] = ''
    # 公告发布日期， 无则不填
    item['export_flag'] = False
    item['downloaded'] = False
    # 爬虫时间
    item['timestamp'] = int(time.time())

    return item


def get_notice():
    item = {}
    item['src_id'] = ''

    # 爬虫时间
    item['timestamp'] = int(time.time())
    # item['write_time'] = ''  # 编写时间
    item['source_url'] = ''
    item['file_url'] = ''  # 文件获取url
    item['file_size'] = 0
    item['file_type'] = ''  # 文件类型
    # item['file_time'] = ''
    # item['file_path'] = ''
    # item['file_hash'] = ''
    item['oss_path'] = ''
    # item['page_num'] = 0
    item['downloaded'] = False
    item['column'] = ''
    item['plate'] = ''
    item['type'] = ''
    item['industry_id'] = ''
    # item['author'] = ''
    item['category_id'] = ''
    item['export_flag'] = False
    item['export_version'] = 0
    # item['write_organ'] = ''
    item['org_id'] = ''
    # item['payment_type'] = ''
    # item['rating'] = ''
    # item['rating_adjust'] = ''
    # item['report_id'] = ''
    # item['report_catagory'] = ''
    # item['rnd'] = ''
    # item['sitename'] = ''
    # item['source'] = ''
    # item['status'] = ''
    item['stock_code'] = ''
    item['stock_name'] = ''
    item['publish'] = ''
    # item['summary'] = ''
    # item['tags'] = ''
    #     item['title'] = ''  # 报告名称
    return item


def gen_notice_src_id(prefix):
    return get_hash_id_enhance(prefix)


def standardized_item(item):
    rst = copy.copy(item)
    must = {'market', 'oss_path', 'file_type', 'page_num', 'file_name',
            'sitename', 'source', 'report_category', 'source_url',
            'downloaded', 'title', 'file_url', 'payment_type',
            'dev_mail'}
    optional = {'author', 'file_path', 'time', 'summary', 'file_size'}
    reserved = {'file_time', 'analyst1', 'analyst2', 'analyst3', 'rating',
                'rating_adjust', 'write_time', 'write_organ', 'stock_code', 'stock_name',
                'abc_indstry_code', 'sw_indstry_code', 'concept', 'region', 'company',
                'investor', 'product', 'person', 'report_img', 'table_list',
                'report_id', 'report_list'}
    auto = {'create_time', 'update_time'}

    error_msg = ''
    warning_msg = ''
    for key, value in rst.items():
        if key in must:
            error_msg += '' if value else 'standardization id failed! item must have {0}.\n'.format(key)
        elif key in reserved:
            error_msg += 'standardization id failed! item["{0}"] is reserved.'.format(key) if value else ''
        elif key in auto:
            warning_msg = "item's {} argument deprecated. pyspider can auto append".format(key)
            print(warning_msg)
        elif key not in optional:
            error_msg = 'standardization id failed! item can not have {0}. -> {0}: {1}'.format(key, value)
    if error_msg:
        raise ValueError(error_msg)

    for key in [x for x in optional | reserved if x not in rst]:
        rst[key] = ''

    if not set(must).issubset(set(rst.keys())):
        raise ValueError('standardization id failed! ({}) not be setted.'
                         .format(' '.join(must - set(rst.keys()))))
    return rst


def change_url(url, site_url, source_url=None):
    """
    可以处理大部分从网站抓取的链接不规范的问题
    修改url为标准链接
    :param url: 获得a链接
    :param site_url: a链接所在域名
    :param source_url: a链接所在的页面
    :return:
    """
    if not url:
        return None

    # site_url 不能为空
    if not site_url:
        return None
    else:
        # site_url 必须规范
        # 若site_url以"/"结尾那么结尾的"/"不要
        site_url = site_url if site_url[-1] != '/' else site_url[:-1]
        if not site_url.startswith('https://') and not site_url.startswith('http://'):
            return None

    # 如果source_url不规则
    if source_url:
        # 如果source_url不为空,但是不以site_url域名为开始，那么source_url有问题
        # 若source_url以"/"结尾那么结尾的"/"不要
        source_url = source_url if source_url[-1] != '/' else source_url[:-1]
        if not source_url.startswith(site_url):
            return None

    if 'http://' not in url and 'https://' not in url:
        if url.startswith('/'):
            return '%s%s' % (site_url, url)

        elif url.startswith('./'):
            url = url[1:]
            if source_url:
                return '%s%s' % (source_url, url)
            else:
                return None
        elif url.startswith('../'):
            url = url[2:]
            source_url = source_url[:source_url.rfind('/')]
            return '%s%s' % (source_url, url)
        else:
            return None
    else:

        if not url.startswith(site_url):
            return None
    return url


local_month = {
    'Enero': '1',
    'Febrero': '2',
    'Marzo': '3',
    'Abril': '4',
    'Mayo': '5',
    'Junio': '6',
    'Julio': '7',
    'Agosto': '8',
    'Septiembre': '9',
    'Octubre': '10',
    'Noviembre': '11',
    'Diciembre': '12',
    'January': '1',
    'February': '2',
    'March': '3',
    'April': '4',
    'May': '5',
    'June': '6',
    'July': '7',
    'August': '8',
    'September': '9',
    'October': '10',
    'November': '11',
    'December': '12',
    'Jan': '1',
    'Feb': '2',
    'Mar': '3',
    'Apr': '4',
    'Jun': '6',
    'Jul': '7',
    'Aug': '8',
    'Sep': '9',
    'Oct': '10',
    'Nov': '11',
    'Dec': '12',
}


def trans_month(input):
    if local_month.get(input) is None:
        return ''
    return local_month.get(input)
